package com.github.fork.plugin;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;

/**
 * 数据源横切面
 * @author Jerry Liu
 * @since 2017/3/29
 */
public class DataSourceAdvice {

    /***
     * 拦截目标方法，获取由@DataSource指定的数据源标识，设置到线程存储中以便切换数据源
     * @param joinPoint
     * @throws Exception
     */
    public void invoke(JoinPoint joinPoint) throws Exception {
        Class<?> target = joinPoint.getTarget().getClass();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        for (Class<?> clazz : target.getInterfaces()) {
            resolveDataSource(clazz, signature.getMethod());
        }

        resolveDataSource(target, signature.getMethod());
    }

    /**
     * 提取目标对象方法注解和类型注解中的数据源标识
     * @param clazz 目标类
     * @param method 目标方法
     */
    private void resolveDataSource(Class<?> clazz, Method method) {

        try {
            Class<?>[] types = method.getParameterTypes();

            // 默认使用类型注解
            if (clazz.isAnnotationPresent(DataSource.class)) {
                DataSource type = clazz.getAnnotation(DataSource.class);
                DataSourceSwitcher.setDataSource(type.value().name());
            }

            Method m = clazz.getMethod(method.getName(), types);

            // 方法注解可以覆盖类型注解
            if (m != null && m.isAnnotationPresent(DataSource.class)) {
                DataSource type = m.getAnnotation(DataSource.class);
                DataSourceSwitcher.setDataSource(type.value().name());
            }
        } catch (Exception e) {

        }
    }
}
